/*
 * SyncResource.java
 *
 * Created on April 12, 2007, 1:39 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.atomojo.app.admin;

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Iterator;
import java.util.logging.Level;
import org.atomojo.app.App;
import org.atomojo.app.client.XMLRepresentationParser;
import org.atomojo.app.db.DB;
import org.atomojo.app.db.RemoteApp;
import org.infoset.xml.Document;
import org.infoset.xml.InfosetFactory;
import org.infoset.xml.ItemConstructor;
import org.infoset.xml.ItemDestination;
import org.infoset.xml.XMLException;
import org.infoset.xml.util.DocumentDestination;
import org.infoset.xml.util.DocumentSource;
import org.infoset.xml.util.WriterItemDestination;
import org.restlet.data.CharacterSet;
import org.restlet.data.MediaType;
import org.restlet.data.Reference;
import org.restlet.data.Status;
import org.restlet.representation.OutputRepresentation;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ServerResource;

/**
 *
 * @author alex
 */
public class RemoteAppsResource extends ServerResource implements AdminXML
{
   
   
   /** Creates a new instance of SyncResource */
   public RemoteAppsResource() {
      setNegotiated(false);
   }
   
   public Representation get()
   {
      final DB db = (DB)getRequest().getAttributes().get(App.DB_ATTR);
      Representation rep = new OutputRepresentation(MediaType.APPLICATION_XML) {
         public void write(OutputStream os) 
            throws IOException
         {
            try {
               Iterator<RemoteApp> apps = db.getRemoteApps();
               Writer out = new OutputStreamWriter(os,"UTF-8");
               ItemDestination dest = new WriterItemDestination(out,"UTF-8");
               ItemConstructor constructor = InfosetFactory.getDefaultInfoset().createItemConstructor();
               dest.send(constructor.createDocument());
               dest.send(constructor.createElement(AdminXML.NM_APPS));
               while (apps.hasNext()) {
                  RemoteApp app = apps.next();
                  app.marshall();;
                  DocumentSource.generate(app.getElement(),false,dest);
               }
               dest.send(constructor.createElementEnd(AdminXML.NM_APPS));
               dest.send(constructor.createDocumentEnd());
               out.flush();
               out.close();
            } catch (XMLException ex) {
               getContext().getLogger().log(Level.SEVERE,"Cannot get list of remotes from DB: "+ex.getMessage(),ex);
               getResponse().setStatus(Status.SERVER_ERROR_INTERNAL,"Cannot get list of remotes due to XML DB error.");
            }
         }
      };
      rep.setCharacterSet(CharacterSet.UTF_8);
      return rep;
   }
   
   public Representation post(Representation entity)
   {
      if (!XMLRepresentationParser.isXML(entity.getMediaType())) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("Non-XML media type for entity body: "+entity.getMediaType().getName());
      }
      final DB db = (DB)getRequest().getAttributes().get(App.DB_ATTR);
      XMLRepresentationParser parser = new XMLRepresentationParser();
      Document doc = null;
      
      try {
         DocumentDestination dest = new DocumentDestination();
         parser.parse(entity,AdminApplication.createAdminDocumentDestination(dest,AdminXML.NM_APP));
         doc = dest.getDocument();
         RemoteApp app = new RemoteApp(db,doc.getDocumentElement());
         if (app.exists()) {
            getResponse().setStatus(Status.CLIENT_ERROR_CONFLICT);
            return new StringRepresentation("Remote app with name "+app.getName()+" already exists.");
         }
         if (app.create()) {
            getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
            Reference ref = new Reference(getRequest().getResourceRef().toString()+"/"+app.getName());
            getResponse().setLocationRef(ref);
            return null;
         } else {
            getContext().getLogger().severe("Cannot store XML for remote app");
            getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
            return new StringRepresentation("Internal error, see logs.");
         }
      } catch (Exception ex) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("XML parse error: "+ex.getMessage());
      }
      
   }
   
}
